﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HtmlParser
{
    abstract class Token
    {
        public abstract bool IsMe(int c);
        public abstract bool CanNest { get; }
		public static bool IsLetter(int c)
        {
            return (c >= 'a' && c <= 'z')
                || (c >= 'A' && c <= 'Z')
                //|| (c >= '0' && c <= '9')
                ;
        }
        public static bool IsBlank(int c)
        {
            return c == '\r'
                || c == '\n'
                || c == ' '
                || c == '\t'
                ;
        }
		public static bool IsNotBlank(int c)
		{
			return c != '\r'
				&& c != '\n'
				&& c != ' '
				&& c != '\t'
				&& c != 0
				;
		}
    }

	class TokenCollection<T> : IEnumerable<T> where T : Token
	{
		public TokenCollection()
		{
			list = new List<T>();
		}
		private readonly List<T> list;
		public void Add(T t)
		{
			list.Add(t);
		}

		public T Check(int c)
		{
			foreach (var token in list)
			{
				if (token.IsMe(c))
				{
					return token;
				}
			}
			return null;
		}


		IEnumerator<T> IEnumerable<T>.GetEnumerator()
		{
			return list.GetEnumerator();
		}
		IEnumerator IEnumerable.GetEnumerator()
		{
			return list.GetEnumerator();
		}
	}

	class HtmlTagTokenCollection : TokenCollection<HtmlTagToken>
	{
		public HtmlTagToken CheckA(int c)
		{
			foreach (var t in this)
			{
				if (t.IsA(c)) return t;
			}
			return null;
		}
		public HtmlTagToken CheckB(int c)
		{
			foreach (var t in this)
			{
				if (t.IsB(c)) return t;
			}
			return null;
		}
	}

	class HtmlTagToken : Token
    {
        public HtmlTagToken(int a, int b)
        {
            this.a = a;
            this.b = b;
        }
        public HtmlTagToken(int c) : this(c, c) { }
        public HtmlTagToken(string s)
        {
            if (s == null) return;
            if (s.Length > 0)
            {
                this.a = this.b = s[0];
            }
            if (s.Length > 1)
            {
                this.b = s[1];
            }
        }

        public override bool IsMe(int c)
        {
            return c == a || c == b;
        }
        public bool IsA(int c)
        {
            return c == a;
        }
        public bool IsB(int c)
        {
            return c == b;
        }
        public int a;
        public int b;

        public override bool CanNest
        {
            //get { return a != b; }
            get { return false; }
		}

        public override string ToString()
        {
            return String.Format("{0}/{1}", (char)a, (char)b);
        }

        public static bool IsTagNameFirst(int c)
        {
            return c == '/' || c == '!' || IsLetter(c);
        }

    }
}
